#include "tagged_stack.h"
#include "../atomic/cpu_pause.h"
#include <stdlib.h>

void tagged_stack_init(tagged_stack_t* stack) {
    tagged_ptr_t initial = make_tagged_ptr(NULL, 0);
    atomic_tagged_store(&stack->top, initial, memory_order_relaxed);
}

bool tagged_stack_push(tagged_stack_t* stack, void* data) {
    node_t* new_node = malloc(sizeof(node_t));
    if (!new_node) return false;
    
    new_node->data = data;
    
    tagged_ptr_t top;
    do {
        top = atomic_tagged_load(&stack->top, memory_order_acquire);
        new_node->next = get_ptr(top);
        
        tagged_ptr_t new_top = make_tagged_ptr(new_node, get_tag(top) + 1);
        
        if (atomic_tagged_compare_exchange_weak(
                &stack->top,
                &top,
                new_top,
                memory_order_release,
                memory_order_relaxed)) {
            return true;
        }
        cpu_pause();
    } while (1);
}

void* tagged_stack_pop(tagged_stack_t* stack) {
    tagged_ptr_t top;
    do {
        top = atomic_tagged_load(&stack->top, memory_order_acquire);
        node_t* node = get_ptr(top);
        
        if (node == NULL) {
            return NULL;  // 栈为空
        }
        
        tagged_ptr_t new_top = make_tagged_ptr(
            node->next,
            get_tag(top) + 1
        );
        
        if (atomic_tagged_compare_exchange_weak(
                &stack->top,
                &top,
                new_top,
                memory_order_release,
                memory_order_relaxed)) {
            void* data = node->data;
            free(node);
            return data;
        }
        cpu_pause();
    } while (1);
}

bool tagged_stack_is_empty(tagged_stack_t* stack) {
    tagged_ptr_t top = atomic_tagged_load(&stack->top, memory_order_acquire);
    return get_ptr(top) == NULL;
} 